# -*- coding: utf-8 -*-
import docx
from docx import Document
from docx.shared import Pt, Cm, Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
import os
import sys

# --- 1. 定义样式名称常量 ---
STYLE_NORMAL = '正文'  # 对应规范中的正文
STYLE_HEADING_1 = '标题 1'  # 对应规范中的一级标题 "一、"
STYLE_HEADING_2 = '标题 2'  # 对应规范中的二级标题 "（一）"
STYLE_HEADING_3 = '标题 3'  # 对应规范中的三级标题 "1."
STYLE_TITLE = '大标题'  # 对应规范中的大标题


# --- 2. 辅助函数：设置段落格式 ---
def set_paragraph_format(paragraph, alignment=WD_ALIGN_PARAGRAPH.JUSTIFY, first_line_indent=True,
                         space_before=0, space_after=0, line_spacing=28):
    """
    设置段落格式。
    :param paragraph: 要设置的段落对象。
    :param alignment: 对齐方式，默认两端对齐。
    :param first_line_indent: 是否首行缩进2字符。
    :param space_before: 段前间距（磅）。
    :param space_after: 段后间距（磅）。
    :param line_spacing: 行距（固定值，磅）。
    """
    paragraph.alignment = alignment
    paragraph_format = paragraph.paragraph_format
    paragraph_format.space_before = Pt(space_before)
    paragraph_format.space_after = Pt(space_after)
    paragraph_format.line_spacing_rule = docx.enum.text.WD_LINE_SPACING.EXACTLY
    paragraph_format.line_spacing = Pt(line_spacing)

    if first_line_indent:
        paragraph_format.first_line_indent = Pt(2 * 10.5)  # 2字符缩进 (假设三号字约10.5pt宽)
    else:
        paragraph_format.first_line_indent = Pt(0)


# --- 3. 辅助函数：设置字体 ---
def set_font(run, name, size):
    """
    设置字体名称和大小。
    :param run: Run 对象。
    :param name: 字体名称 (如 '方正仿宋简体')。
    :param size: 字体大小 (Pt 对象)。
    """
    run.font.name = name
    # 为兼容中文，需要显式设置 east_asia 字体
    r = run._element
    r.rPr.eastAsia = OxmlElement('w:eastAsia')
    r.rPr.eastAsia.set(qn('w:val'), name)
    run.font.size = size


# --- 4. 核心函数：创建和应用正文，各级标题样式 ---
def create_styles(doc):
    """
    在文档中创建符合规范的样式。
    :param doc: Document 对象。
    """
    styles = doc.styles

    # --- 正文样式 ---
    style_normal = styles.add_style(STYLE_NORMAL, docx.enum.style.WD_STYLE_TYPE.PARAGRAPH)
    style_normal.base_style = styles['Normal']
    font_normal = style_normal.font
    font_normal.name = '方正仿宋简体'
    font_normal._element.rPr.eastAsia = OxmlElement('w:eastAsia')
    font_normal._element.rPr.eastAsia.set(qn('w:val'), '方正仿宋简体')
    font_normal.size = Pt(16)  # 三号字
    # 段落格式在应用时设置，因为样式可能被修改

    # --- 一级标题样式 "一、" ---
    style_h1 = styles.add_style(STYLE_HEADING_1, docx.enum.style.WD_STYLE_TYPE.PARAGRAPH)
    font_h1 = style_h1.font
    font_h1.name = '方正黑体简体'
    font_h1._element.rPr.eastAsia = OxmlElement('w:eastAsia')
    font_h1._element.rPr.eastAsia.set(qn('w:val'), '方正黑体简体')
    font_h1.size = Pt(16)  # 三号字
    # 段落格式在应用时设置

    # --- 二级标题样式 "（一）" ---
    style_h2 = styles.add_style(STYLE_HEADING_2, docx.enum.style.WD_STYLE_TYPE.PARAGRAPH)
    font_h2 = style_h2.font
    font_h2.name = '方正楷体简体'
    font_h2._element.rPr.eastAsia = OxmlElement('w:eastAsia')
    font_h2._element.rPr.eastAsia.set(qn('w:val'), '方正楷体简体')
    font_h2.size = Pt(16)  # 三号字
    # 段落格式在应用时设置

    # --- 三级标题样式 "1." ---
    style_h3 = styles.add_style(STYLE_HEADING_3, docx.enum.style.WD_STYLE_TYPE.PARAGRAPH)
    font_h3 = style_h3.font
    font_h3.name = '方正仿宋简体'
    font_h3._element.rPr.eastAsia = OxmlElement('w:eastAsia')
    font_h3._element.rPr.eastAsia.set(qn('w:val'), '方正仿宋简体')
    font_h3.bold = True  # 加粗
    font_h3.size = Pt(16)  # 三号字
    # 段落格式在应用时设置

    # --- 大标题样式 ---
    style_title = styles.add_style(STYLE_TITLE, docx.enum.style.WD_STYLE_TYPE.PARAGRAPH)
    font_title = style_title.font
    font_title.name = '方正小标宋简体'
    font_title._element.rPr.eastAsia = OxmlElement('w:eastAsia')
    font_title._element.rPr.eastAsia.set(qn('w:val'), '方正小标宋简体')
    font_title.size = Pt(22)  # 二号字
    paragraph_format_title = style_title.paragraph_format
    paragraph_format_title.alignment = WD_ALIGN_PARAGRAPH.CENTER
    # 段前空行在添加段落时处理

    return style_normal, style_title, style_h1, style_h2, style_h3


# --- 5. 辅助函数：检查文件占用 ---
def is_file_locked(filepath):
    """检查文件是否可能被其他程序锁定。"""
    if not os.path.exists(filepath):
        return False
    try:
        with open(filepath, 'r+'):
            pass
        return False
    except PermissionError:
        return True
    except OSError:
        return True
    except Exception:
        return True


# --- 6. 主程序入口 ---
def main():
    """
    主程序流程。
    """
    # --- 获取用户输入 ---
    print("--- Word 一键排版程序 ---")
    input_file_path = input("请输入要排版的原始 .docx 文件路径 (或按 Enter 跳过创建新文档): ").strip()
    output_file_path = input("请输入排版后保存的 .docx 文件路径 (例如: formatted_output.docx): ").strip()

    if not output_file_path:
        print("错误：必须提供输出文件路径。")
        sys.exit(1)

    # --- 创建或加载文档 ---
    doc = None
    if input_file_path and os.path.exists(input_file_path) and input_file_path.endswith('.docx'):
        try:
            doc = Document(input_file_path)
            print(f"已加载文档: {input_file_path}")
        except Exception as e:
            print(f"加载文档 '{input_file_path}' 时出错: {e}")
            print("将创建一个新文档。")
            doc = Document()
    else:
        if input_file_path:
            print(f"输入文件 '{input_file_path}' 不存在或不是 .docx 文件，将创建一个新文档。")
        else:
            print("未提供输入文件，将创建一个新文档。")
        doc = Document()

    # --- 设置页面边距 ---
    sections = doc.sections
    for section in sections:
        section.top_margin = Cm(3.7)
        section.bottom_margin = Cm(3.5)
        section.left_margin = Cm(2.8)
        section.right_margin = Cm(2.6)
    print("已设置页面边距。")

    # --- 创建样式 ---
    style_normal, style_title, style_h1, style_h2, style_h3 = create_styles(doc)
    print("已创建文档样式。")

    # --- 应用段落格式到现有内容 (如果加载了文档) ---
    if input_file_path and os.path.exists(input_file_path):
        print("正在应用段落格式到现有内容...")
        for paragraph in doc.paragraphs:
            # 根据内容猜测并应用样式
            text = paragraph.text.strip()
            if not text:
                continue

            # 应用正文样式作为默认
            paragraph.style = doc.styles[STYLE_NORMAL]
            # 设置段落格式 (首行缩进、行距等)
            set_paragraph_format(paragraph)

            # 简单尝试识别标题并应用对应样式 (这需要内容有明确格式)
            # 注意：这只是一个非常基础的示例，实际应用中可能需要更复杂的逻辑
            if text.startswith('一、') or text.startswith('二、') or text.startswith('三、'):
                paragraph.style = doc.styles[style_h1]
                set_paragraph_format(paragraph, first_line_indent=False)  # 标题无首行缩进
            elif text.startswith('（一）') or text.startswith('(一)'):
                paragraph.style = doc.styles[STYLE_HEADING_2]
                set_paragraph_format(paragraph, first_line_indent=False)
            elif text.startswith('1.') or text.startswith('2.') or text.startswith('3.'):
                paragraph.style = doc.styles[STYLE_HEADING_3]
                # 三级标题后通常跟正文，这里假设它本身需要格式化，句号后紧跟正文需手动处理
                set_paragraph_format(paragraph, first_line_indent=False)

        print("段落格式应用完成。")

    # --- 添加示例内容 (如果创建了新文档) ---
    if not (input_file_path and os.path.exists(input_file_path)):
        print("正在添加示例内容...")
        # 添加大标题
        title_para = doc.add_paragraph()
        title_run = title_para.add_run("这是一个示例大标题")
        set_font(title_run, '方正小标宋简体', Pt(22))  # 二号
        title_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
        # 大标题上空一行，通过在前一段落（或文档开始）后添加空段落实现
        # 或者在大标题段落本身设置段前间距，但样式已设置居中，这里手动添加空行更直观
        # doc.add_paragraph() # 在大标题前添加一个空段落来实现“上空一行”

        # 添加正文
        p1 = doc.add_paragraph(style=STYLE_NORMAL)
        p1.add_run("这是正文的第一段。正文使用方正仿宋简体，三号字体，两端对齐，首行缩进2字符，行距固定值28磅。")
        set_paragraph_format(p1)  # 应用段落格式

        p2 = doc.add_paragraph(style=STYLE_NORMAL)
        p2.add_run("这是正文的第二段，继续演示格式。")

        # 添加一级标题
        h1 = doc.add_paragraph("一、这是一级标题", style=STYLE_HEADING_1)
        set_paragraph_format(h1, first_line_indent=False)  # 无首行缩进

        # 添加正文
        p3 = doc.add_paragraph(style=STYLE_NORMAL)
        p3.add_run("这是一级标题下的正文内容。")

        # 添加二级标题 (无句号)
        h2_1 = doc.add_paragraph("（一）这是二级标题（无句号）", style=STYLE_HEADING_2)
        set_paragraph_format(h2_1, first_line_indent=False)

        # 添加二级标题 (有句号)
        h2_2 = doc.add_paragraph("（二）这是二级标题（有句号）。", style=STYLE_HEADING_2)
        set_paragraph_format(h2_2, first_line_indent=False)
        # 句号后紧跟正文 - 这里紧接着添加正文段落
        p4 = doc.add_paragraph(style=STYLE_NORMAL)
        p4.add_run("这是紧跟在有句号的二级标题后的正文。")

        # 添加三级标题
        h3 = doc.add_paragraph("1. 这是三级标题。", style=STYLE_HEADING_3)
        set_paragraph_format(h3, first_line_indent=False)
        # 句号后紧跟正文
        p5 = doc.add_paragraph(style=STYLE_NORMAL)
        p5.add_run("这是紧跟在三级标题后的正文。")

        # 添加无序列表项示例 (模拟)
        p6 = doc.add_paragraph(style=STYLE_NORMAL)
        p6.add_run("• 这是一个列表项。")
        # 注意：python-docx 对列表的支持有限，复杂列表可能需要手动调整或使用项目符号/编号功能

        p7 = doc.add_paragraph(style=STYLE_NORMAL)
        p7.add_run("这是最后一段正文内容。")

        print("示例内容添加完成。")

    # --- 添加落款 (示例) ---
    print("正在添加示例落款...")
    # 添加空行以将落款置于底部附近（实际精确控制可能需要分节符）
    for _ in range(3):  # 添加几行空行
        doc.add_paragraph()

    # 单位名称 (居中)
    unit_para = doc.add_paragraph("某某单位", style=STYLE_NORMAL)
    unit_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
    set_paragraph_format(unit_para, first_line_indent=False)  # 落款通常无首行缩进

    # 日期 (右对齐，距右8字符)
    date_para = doc.add_paragraph("2023年10月27日", style=STYLE_NORMAL)
    date_para.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    # 设置右缩进约为8个字符 (假设三号字约10.5pt宽)
    date_para.paragraph_format.right_indent = Pt(8 * 10.5)
    set_paragraph_format(date_para, first_line_indent=False)

    print("示例落款添加完成。")

    # --- 全文刷 Times New Roman 字体 (仅对 Run 的 ASCII 字符) ---
    # 注意：python-docx 不能直接“刷”整个文档的非中文字体。
    # 它设置的是字体的 name (西方字体) 和 east_asia (中文字体)。
    # 我们已经在样式和 run 中设置了中文字体。对于西文，run.font.name 默认就是应用的。
    # 要强制所有 run 的西文部分为 Times New Roman，需要遍历所有 run。
    # 但这会覆盖之前设置的中文字体的 'name' 部分，可能不是最佳实践。
    # 更好的方式是确保在设置中文字体时，同时正确设置了 eastAsia，并且 run.font.name 设置为西文字体。
    # python-docx 通常会自动处理西文和中文使用不同字体。
    # 因此，我们确保在创建样式和添加 run 时已经正确设置了字体。
    # 如果确实需要强制刷西文字体，可以取消下面的注释，但这可能干扰中文字体设置。
    """
    print("正在尝试应用 Times New Roman 到西文字符...")
    for paragraph in doc.paragraphs:
        for run in paragraph.runs:
            # 这会设置西文部分字体，但可能影响中文字体显示（如果 name 被覆盖）
            # run.font.name = 'Times New Roman'
            # 更安全的方式是只在 run 内容包含西文时设置
            # if any(ord(char) < 128 for char in run.text): # 检查是否有 ASCII 字符
            #     run.font.name = 'Times New Roman'
            pass # 已在样式和 run 设置中处理
    print("西文字体应用提示完成。")
    """

    # --- 保存文档 ---
    print(f"正在保存文档到: {output_file_path}")
    if is_file_locked(output_file_path):
        print(f"警告: 文件 '{output_file_path}' 可能正被另一个程序打开。请关闭该文件后再尝试保存。")
        confirm = input("是否仍要尝试保存？(y/N): ").strip().lower()
        if confirm != 'y':
            print("保存操作已取消。")
            sys.exit(0)

    try:
        doc.save(output_file_path)
        print(f"文档已成功保存到: {output_file_path}")
        print("--- 排版完成 ---")
    except Exception as e:
        print(f"保存文档时出错: {e}")
        sys.exit(1)


# --- 程序入口 ---


def is_paragraph_numbered(paragraph):
    """
    检测一个段落是否应用了自动编号（多级列表或项目符号）。

    这是检测自动编号最核心、最直接的方法。
    它检查段落的 XML 属性中是否存在 <w:numPr> 元素。

    Args:
        paragraph (docx.text.paragraph.Paragraph): python-docx 的段落对象。

    Returns:
        bool: 如果段落有自动编号则返回 True，否则返回 False。
    """
    # 获取段落的底层 XML 元素
    p_element = paragraph._element

    # 查找 <w:pPr> (段落属性) 元素
    p_pr = p_element.find(qn('w:pPr'))
    if p_pr is None:
        return False  # 没有段落属性，肯定没有编号

    # 在 <w:pPr> 中查找 <w:numPr> (编号属性) 元素
    num_pr = p_pr.find(qn('w:numPr'))

    # 如果找到了 numPr 元素，说明该段落应用了自动编号
    return num_pr is not None


def get_numbered_level(paragraph):
    """
    获取自动编号段落的级别。如果无编号，返回 None。

    Returns:
        int or None: 编号级别 (1, 2, 3...) 或 None。
    """
    p_element = paragraph._element
    p_pr = p_element.find(qn('w:pPr'))
    if p_pr is not None:
        num_pr = p_pr.find(qn('w:numPr'))
        if num_pr is not None:
            ilvl = num_pr.find(qn('w:ilvl'))
            if ilvl is not None:
                # w:val 属性的值是级别，例如 w:val="0" 表示第一级
                level_val = ilvl.get(qn('w:val'))
                # 注意：ilvl 通常从 0 开始，所以 +1
                return int(level_val) + 1 if level_val is not None else None
    return None

if __name__ == "__main__":
    file = r"D:\工作\一键排版\排版后_第一周报告.docx"
    docx = Document(file)
    paragraphcnt = 0



    for paragraph in docx.paragraphs:
        paragraphcnt = paragraphcnt + 1
        if is_paragraph_numbered(paragraph):
            print(f"段落 '{paragraph.text[:30]}...' 有自动编号")
            # 检测自动编码等级
            # level = get_numbered_level(paragraph)
            # if level is not None:
            #     print(f"第几{paragraphcnt}段落 '{paragraph.text[:20]}...' 是第 {level} 级自动编号")
            # 在这里，你可以根据需要进一步判断是几级标题
            # 或者移除编号，应用你的自定义样式
        else:
            print(f"段落 '{paragraph.text[:30]}...' 无自动编号")




        if paragraph.text == '':
            paragraphcnt = paragraphcnt - 1
            continue
        #print('这是第%s段' % paragraphcnt)
        #print(paragraph.text)
